Skip to main content
This guide covers how to encrypt and decrypt data in PVAC-HFHE, including advanced features like depth hints and multi-slot encryption.

Basic encryption

The enc_value function encrypts a single 64-bit unsigned integer:

Function signature

From include/pvac/ops/encrypt.hpp:740-742:
enc_value is a wrapper around enc_value_depth with depth hint 0, suitable for fresh encryptions.

Basic decryption

The dec_value function decrypts a ciphertext back to a field element:

Function signature

From include/pvac/ops/decrypt.hpp:77-79:
Always extract the .lo field from the returned Fp struct. The .hi field contains the upper 63 bits of the 127-bit field element.

Encryption with depth hints

For computations at specific circuit depths, use enc_value_depth to preallocate noise budget:
From include/pvac/ops/encrypt.hpp:732-738:

When to use depth hints

Higher depth hints allocate more noise budget but increase encryption time and ciphertext size.

Ciphertext structure

From include/pvac/core/types.hpp:116-121:

Components explained

std::vector<Layer> L
Represents the computation graph layers. Base layers contain randomness seeds, product layers encode multiplications.
std::vector<Edge> E
Edges in the computation graph. Each edge has:
  • layer_id: Which layer it belongs to
  • idx: Index in the multiplicative group (0 to B-1)
  • ch: Sign channel (SGN_P or SGN_M)
  • w: Weight vector (field elements)
  • s: LPN noise bits
std::vector<Fp> c0
Constant term added to the encrypted value.
size_t slots
Number of values packed in this ciphertext (default 1).

Multi-slot encryption

Encrypt vectors of values using enc_values:
From include/pvac/ops/encrypt.hpp:753-756:
Multi-slot encryption packs multiple values into a single ciphertext, enabling SIMD-style operations.

Decryption algorithm

The dec_values function implements the full decryption procedure:
1

Compute layer randomness

For each layer, compute R using PRF with the layer seed
2

Invert randomness

Compute R^(-1) for each layer to unmask edges
3

Accumulate edges

Sum all edges: acc = Σ sign(e) · w · g^idx · R^(-1)
4

Add constant term

Add c0 to the accumulator
From include/pvac/ops/decrypt.hpp:46-75:

Performance characteristics

From benchmark data:

Comparison with other schemes

PVAC-HFHE ciphertexts are 6-85x smaller than RLWE schemes, making them ideal for bandwidth-constrained applications.

Testing correctness

From examples/basic_usage.cpp:59-63:

Edge cases

Encryption randomness

Every encryption is randomized. Two encryptions of the same value produce different ciphertexts:
From examples/basic_usage.cpp:216-221:
Never reuse the same ciphertext for multiple operations. Always create fresh encryptions when needed.

Advanced: Field element encryption

For direct field element encryption, use enc_fp_depth:
This is useful when working directly with field arithmetic.

Next steps

Arithmetic operations

Perform ct_add, ct_mul, ct_sub on ciphertexts

Text encryption

Encrypt and decrypt strings